package com.ming.user.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ming.common.entity.ResultData;
import com.ming.user.JwtToken;
import com.ming.user.LoginResult;
import com.ming.user.User;
import com.ming.user.config.AuthHeadConfig;
import com.ming.user.feign.Oauth2Feign;
import com.ming.user.feign.UserFeign;
import com.ming.user.mapper.UserMapper;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Classname UserService
 * @Description TODO
 * @Date 2021/1/5 13:59
 * @Created by yanming.fu
 */
@Service
@Slf4j
public class UserService {
    /*@Value("${basic.token:Basic Y29pbi1hcGk6Y29pbi1zZWNyZXQ=}")
    private String basicToken ;*/
    @Autowired
    private Oauth2Feign oAuth2FeignClient;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserFeign userFeign;
    @Autowired
    private StringRedisTemplate redisTemplate ;

    public List<User> findUser() {
        List<User> users = userMapper.selectAll();
        Example example = new Example(User.class);
        example.createCriteria().andEqualTo("id", "1");
        List<User> users1 = userMapper.selectByExample(example);
        log.error("当前登陆人:[{}]",this.getCurrentUserId());
        return users;
    }

    /**
     * @Description 获取当前操作的用户对象
     * @return java.lang.Long
     * @date 2021/2/7 15:15
     * @auther yanming.fu
     */
    private String getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 从安全的上下文里面获取用户的ud
        if(authentication!=null){
            String s = authentication.getPrincipal().toString(); // userId ->Long  anonymousUser
            if("anonymousUser".equals(s)){ //是因为用户没有登录访问时,就是这个用户
                return null ;
            }
            return String.valueOf(s) ;
        }
        return null ;
    }

    @GlobalTransactional(rollbackFor = Exception.class,name="ming-system-feign")
    public ResultData testFeign() {
        UUID uuid = UUID.randomUUID();
        User user = User.builder().age(22L).name("蒙面人").id(uuid.toString().replace("-","")).build();
        userMapper.insert(user);
        ResultData resultData = userFeign.echo("1");
        return resultData;
    }

    public LoginResult login(String username, String password) {

        log.info("用户{}开始登录", username);
        // 1 获取token 需要远程调用authorization-server 该服务
        ResponseEntity<JwtToken> tokenResponseEntity = oAuth2FeignClient.getToken("password", username, password, "admin_type", AuthHeadConfig.getHeader());
        if(tokenResponseEntity.getStatusCode()!= HttpStatus.OK){
            throw new RuntimeException("远程失败");
        }
        JwtToken jwtToken = tokenResponseEntity.getBody();
        log.info("远程调用授权服务器成功,获取的token为{}", JSON.toJSONString(jwtToken,true));
        String token = jwtToken.getAccessToken() ;

        // 2 查询我们的菜单数据
        Jwt jwt = JwtHelper.decode(token);
        String jwtJsonStr = jwt.getClaims();
        JSONObject jwtJson = JSON.parseObject(jwtJsonStr);
        String user_name = String.valueOf(jwtJson.getString("user_name")) ;
        log.error("【userId:{}】",user_name);

        // 3 权限数据怎么查询 -- 不需要查询的，因为我们的jwt 里面已经包含了
        JSONArray authoritiesJsonArray = jwtJson.getJSONArray("authorities");
        List<SimpleGrantedAuthority> authorities = authoritiesJsonArray.stream() // 组装我们的权限数据
                .map(authorityJson->new SimpleGrantedAuthority(authorityJson.toString()))
                .collect(Collectors.toList());
        // 1 将该token 存储在redis 里面，配置我们的网关做jwt验证的操作
        redisTemplate.opsForValue().set(token,"", jwtToken.getExpiresIn() , TimeUnit.SECONDS);
        //2 我们返回给前端的Token 数据，少一个bearer：
        return new LoginResult(jwtToken.getTokenType()+" "+token, null, authorities);

    }
}
